/*
 * simulation_transponder_EnergySaving_TransponderSaving����汾��ȫ��ȷ
 */

package VNFmeetsVON_MRDP_5modes;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.net2plan.interfaces.networkDesign.Demand;
import com.net2plan.interfaces.networkDesign.Link;
import com.net2plan.interfaces.networkDesign.NetPlan;
import com.net2plan.interfaces.networkDesign.NetworkLayer;
import com.net2plan.interfaces.networkDesign.Node;
import com.net2plan.interfaces.networkDesign.Route;
import com.net2plan.internal.ErrorHandling;
import com.net2plan.libraries.GraphUtils;
import com.net2plan.libraries.WDMUtils;

import cern.colt.matrix.tdouble.DoubleMatrix1D;


public class Combination10 {
	
//	*************************************************************************************************************************************
	
	public static int numberofallslot = 358 ;
	public static double BPSKmaxlength = 4000.0;
	public static double QPSKmaxlength = 2000.0;
	public static double QAM_8maxlength = 1000.0;
	public static double QAM_16maxlength = 500.0;
	public static double QAM_32maxlength = 250.0;
	public static boolean sign = false ; 
	public int numberofslot;
	public static int numberofkshortestpath=3;
	public static int nodemappingknum = 2;
	public static boolean linkmappingsign = false;
	


//	***************************************************************************************
	public static NetPlan removeAllLayerDemand(NetPlan netplan){
		for (NetworkLayer networklayer : netplan.getNetworkLayers()){
			netplan.removeAllDemands(networklayer);
		} 
		return netplan;
	}


	
//	***************************************************************************************
//ɾ��netplan�г����������������в�
	public static NetPlan removeLayers(NetPlan netplan){
		List<Long> names = new ArrayList<Long>();
		int numberofnetworklayers = netplan.getNumberOfLayers();
		for (int i=1;i<numberofnetworklayers;i++){
			Long name = netplan.getNetworkLayer(i).getId();
			names.add(name);
			
		}
		for (Long name : names){
			netplan.removeNetworkLayer(netplan.getNetworkLayerFromId(name));
			netplan = netplan.copy();
		}
		return netplan;
	}




//	***************************************************************************************
//	��������������е�link���������е�slotΪ״̬0,һ����numberofslot������slot������numberofslot������0����net2plan�е�Ч������Link��Attribute����ʾsubstratelinkcapacityofslots=00000������һ����320��0������Ϊ����״̬
//	������Ҫע����ǣ�֮�������ͨ��copy����0�������µĲ��ʱ����Ӧ������0���link�����Լ�substratelinkcapacityofslotsҲ�ᱻ���Ƶ���Ӧ�Ĳ�
//	ͬʱ������Link��CapacityΪnumberofallslot
	public static NetPlan substrateNetplanAttribute(NetPlan netplan){
		Tool_Util tool = new Tool_Util();
		List<Link> links = new ArrayList<Link>();
		List<Node> nodes = new ArrayList<Node>();
		
		nodes = netplan.getNodes();
		links = netplan.getLinks();
		
		String capacityofslots = tool.setAttributeOfSituationOfSlots(numberofallslot);
		
		for (Link link : links){
			link.setAttribute("linkstatus", capacityofslots);
			link.setCapacity(numberofallslot);
		}
		for (Node node : nodes){
			node.setAttribute("TransmitterOne", capacityofslots);
			node.setAttribute("TransmitterTwo", capacityofslots);
			node.setAttribute("ReceiverOne", capacityofslots);
			node.setAttribute("ReceiverTwo", capacityofslots);
		}
		return netplan;
	}
	
	
//	***************************************************************************************	
	public static NodeMappingReturn nodeMapping(NetPlan VNFNetplan, NetPlan SubNetPlan ) {
		
		Tool_Util tool = new Tool_Util();
		
		int numberofVNFnodes,numberofsubnodes;
		int sourcenodeindex,destinationnodeindex;
		
		//��������д����������
		List<Integer> vnflinkcapacitylist = new ArrayList<Integer>();
		//�õ�VNF�����е�����link����
	    List<Link> vnflinklist = VNFNetplan.getLinks();
	    //�õ������д�����������Ϣ���洢�ڼ�����
	    for(Link vnflink:vnflinklist) {
	    	 vnflinkcapacitylist.add((int)vnflink.getCapacity());
	    }
		
		//������������еĽڵ�
		List<Node> subnodes = SubNetPlan.getNodes();
		
		//�������Ľڵ�
		List<Node> VNFnetplannodes = VNFNetplan.getNodes();
		//��������е�VNF�ڵ㣬������Դ��Ŀ�Ľڵ�
		List<Node> vnfnodes = new ArrayList<Node>();
		
		//��������е�VNF����
		List<Integer> VNFseqofVNFnetplan = new ArrayList<Integer>();
		
		
		//���K�����·��������VNF���еĹ��������г���
		List<Integer> lengthofCS = new ArrayList<Integer>();
		
		//���K��·���Ͻڵ�ӳ���ֵ��ϵ
		List<List<Map.Entry<Node, Node>>> tempnodepairlist = new ArrayList<List<Map.Entry<Node,Node>>>();
		
	
		NodeMappingReturn nodemappingreturn = new NodeMappingReturn();
		
		//�����˳��ڵ�ӳ�����,ѡ��ڵ�����м�¼
		Map<Node,Node> vnfnodepair = new HashMap<Node,Node>();
		
		//��˳���¼�ڵ�ӳ���������net2plan�й�
		Map<Node,Node> nodepair = new HashMap<Node,Node>();
		
		
		sign = true;
		
		//����������������еĽڵ���
		numberofsubnodes = SubNetPlan.getNumberOfNodes();
		
		
		//��������еĽڵ���������Դ��Ŀ�Ľڵ�
		numberofVNFnodes = VNFNetplan.getNumberOfNodes();
		
		for(int i =1;i<=numberofVNFnodes-2;i++) {
			vnfnodes.add(VNFnetplannodes.get(i));
		}
		
		Node vnfsourcenode = VNFNetplan.getNode(0);
		Node vnfdestinationnode = VNFNetplan.getNode(numberofVNFnodes-1);
		
		sourcenodeindex = (int)(Math.random()*numberofsubnodes);
		
		
		while(true) {
			
			destinationnodeindex = (int)(Math.random()*numberofsubnodes);
			
			//Դ�ڵ��Ŀ�Ľڵ㲻����ͬһ����
			if(destinationnodeindex!=sourcenodeindex) {
				break;
			}
			
		}
		
		if(sourcenodeindex<0||destinationnodeindex<0) {
			sign =false;
			nodemappingreturn.setSign(sign);
			return nodemappingreturn;
		}
		
		 vnfnodepair.put(vnfsourcenode, SubNetPlan.getNode(sourcenodeindex));
		 vnfnodepair.put(vnfdestinationnode, SubNetPlan.getNode(destinationnodeindex));
				
		
		//�Ƚ�Դ��Ŀ�Ľڵ���Ϊ�Ѳ��𣬺���Ҫ�õ�
		 
		vnfsourcenode.setAttribute("MappedNode", String.valueOf(sourcenodeindex));
		vnfsourcenode.setAttribute("deployed", "1");
	
		vnfdestinationnode.setAttribute("MappedNode", String.valueOf(destinationnodeindex));
		vnfdestinationnode.setAttribute("deployed", "1");
		
		
		
		//��·�ĳ�����Ϊcost
		Map<Link,Double> linkCostMap = new HashMap<Link,Double>();
		for (Link link : SubNetPlan.getLinks()){
				linkCostMap.put(link, link.getLengthInKm());

		}
		
		//���Դ�ڵ��Ŀ�Ľڵ�֮���K�����·��
		List<List<Link>> kshortestpathlist = GraphUtils.getKLooplessShortestPaths(SubNetPlan.getNodes(), SubNetPlan.getLinks(), SubNetPlan.getNode(sourcenodeindex), SubNetPlan.getNode(destinationnodeindex), linkCostMap, nodemappingknum, Double.MAX_VALUE, Integer.MAX_VALUE , Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
		
		
		//��������е�VNF���У�������Դ�ڵ��Ŀ�Ľڵ�
		for(int i = 1;i<=numberofVNFnodes-2;i++) {
			VNFseqofVNFnetplan.add(Integer.valueOf(VNFNetplan.getNode(i).getAttribute("VNF")).intValue());
		}
		
		
		
		for(List<Link> shortestpath : kshortestpathlist) {
			
			//ͳ�ƹ��������еĳ���
			int flag = 0;
			
			//ͳ������·���Ͻڵ�ӳ�����
			Map<Node,Node> tempvnfnodepair = new HashMap<Node,Node>();
			List<Map.Entry<Node, Node>> tempnodepair = new ArrayList<Map.Entry<Node,Node>>();
			
			//���Ҫ�Ƴ��Ľڵ㼯��
			List<Node> removenodelist = new ArrayList<Node>();
			
			//���·�����������нڵ�
			List<Node> tempnodelist = new ArrayList<Node>();
			
			//�Ȱ�·�������ӵ�������
			tempnodelist.add(shortestpath.get(0).getOriginNode());
			
			//����ȡÿ��link���յ�
			for(Link templink : shortestpath) {
				tempnodelist.add(templink.getDestinationNode());
			}
			
			//��ʱ��tempnodelist���水˳����������·�����������нڵ�
			
			//��ʼ�������󹫹������еĳ���
		    for(int i = 0;i<numberofVNFnodes-2;i++) {
		    	
		    	//����tempnodelist�����Ԫ��
		    	for(Node removenode:removenodelist) {
		    		if(tempnodelist.contains(removenode)) {
		    			tempnodelist.remove(removenode);
		    		}
		    	}
		    	
		    	//�õ�������VNF����
		    	int vnftype = VNFseqofVNFnetplan.get(i);
		    	
		    	
		    	//���·���ڵ�����
		    	int numberoftempnode = tempnodelist.size();
		    	
		    	
		    	for(int j = 0;j<numberoftempnode;j++) {
		    		
		    		//�õ��ڵ��ϲ����VNF���༯��
		    		List<Integer> subnodevnflist = new ArrayList<Integer>();
		    		int[] subnodevnf = tool.stringToIntArray(tempnodelist.get(j).getAttribute("VNF"));
		    		for(int a : subnodevnf) {
		    			subnodevnflist.add(a);
		    		}
		    		
		    		if(subnodevnflist.contains(vnftype)) {
		    			
		    			tempvnfnodepair.put(VNFNetplan.getNode(i+1), tempnodelist.get(j));
		    			
		    			//�Ѽ�ֵ��ϵ��װ�ɶ���,���ŵ�����list��
		    			tempnodepair.addAll(tempvnfnodepair.entrySet());
		    			
		    			flag++;
		    			
		    			for(int n = 0;n<j;n++) {
		    				removenodelist.add(tempnodelist.get(n));
		    			}
		    			
		    			break;
		    			
		    		}
		    		
		    	}
		    	
		    }
			
		    lengthofCS.add(flag);
		    tempnodepairlist.add(tempnodepair);
			
		}
		
		
		//�õ����ֵ�Լ���Ӧ��·������
		 int kmax = Collections.max(lengthofCS);
		 int knum = lengthofCS.indexOf(kmax);
		 
		 if(kmax > 0) {
			 
			 //ѡ�е�·��
			 List<Link> selectedpath = kshortestpathlist.get(knum);
			 //·���ϵĽڵ㼯��
			 List<Node> subnodeonpath = new ArrayList<Node>();
				subnodeonpath.add(selectedpath.get(0).getOriginNode());
				for(Link link:selectedpath) {
					subnodeonpath.add(link.getDestinationNode());
				}
			 
			 //�õ�����·�ϵĸ������
			 List<Map.Entry<Node, Node>> tempnodepaironpath =  tempnodepairlist.get(knum);
			 
			 for(Map.Entry<Node, Node> e : tempnodepaironpath) {
				 
				 if(subnodes.indexOf(e.getValue())<0) {
					 sign=false;
					 nodemappingreturn.setSign(sign);
					 return nodemappingreturn;
				 }
				 //�ѽڵ�ӳ������ȴ�������֮���ٷ����ܵ�nodepair��
				 vnfnodepair.put(e.getKey(), e.getValue()); 
				 e.getKey().setAttribute("deployed", "1");
				 e.getKey().setAttribute("MappedNode", String.valueOf(subnodes.indexOf(e.getValue())));
				 
				 Node selecteddc = e.getValue();
				 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
					
				 reusability++;
					
				 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
				 
			 }
	
			 
			 //û�б�ӳ��Ľڵ㼯��
			 List<Node> RV = new ArrayList<Node>();
			 //���м�VNF�ڵ���б���
			 for(int i = 1;i<numberofVNFnodes-1;i++) {
				 if(VNFnetplannodes.get(i).getAttribute("deployed").equals("0")) {
					 RV.add(VNFnetplannodes.get(i));
				 }
			 }
			 
			 for(Node undeployednode : RV) {
				 
				 //��¼����ڵ��������е�λ��
				 int indexinrequestofthisnode=VNFnetplannodes.indexOf(undeployednode);
				 //ǰһ���ڵ�϶��Ѿ��������
				 int indexinrequestofbefore = indexinrequestofthisnode-1;
				 //��¼��������Ѿ�����õĽڵ��������е�λ��
				 int indexinrequestofbehind = 0;
				 for(int i=indexinrequestofthisnode+1;i<numberofVNFnodes;i++) {
					 if(VNFnetplannodes.get(i).getAttribute("deployed").equals("1")) {
						 indexinrequestofbehind=i;
						 break;
					 }
				 }
				 
				 int indexsubnodebefore = Integer.valueOf(VNFnetplannodes.get(indexinrequestofbefore).getAttribute("MappedNode")).intValue();
				 Node subnodebefore = subnodes.get(indexsubnodebefore);
				 
				 int indexsubnodebehind = Integer.valueOf(VNFnetplannodes.get(indexinrequestofbehind).getAttribute("MappedNode")).intValue();
				 Node subnodebehind = subnodes.get(indexsubnodebehind);
				 
				 //����������غϣ�ֱ���������������
				 
				 if(subnodebefore.equals(subnodebehind)) {
					 
					 Node selecteddc = subnodebefore;
					 
					 if(subnodes.indexOf(selecteddc)<0) {
						 sign=false;
						 nodemappingreturn.setSign(sign);
						 return nodemappingreturn;
					 }
					 
					 vnfnodepair.put(undeployednode, selecteddc);
						
					 undeployednode.setAttribute("deployed", "1");
				     undeployednode.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
						 
					 String a = selecteddc.getAttribute("VNF");
			    	 String b = undeployednode.getAttribute("VNF");
				     String c = a.concat(b);
			    	 selecteddc.setAttribute("VNF", c);
						 
					 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
							
					 reusability++;
							
					 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
					 
				 }
				 
				 //�����㲻�غϵ����
				 else {
					 
					 int firstlinkindex=0;
					 int lastlinkindex=0;
					 
					 for(int i =0;i<selectedpath.size();i++) {
						 if(selectedpath.get(i).getOriginNode().equals(subnodebefore)) {
							 firstlinkindex=i;
							 break;
						 }
					 }
					 
					 for(int i =0;i<selectedpath.size();i++) {
						 if(selectedpath.get(i).getDestinationNode().equals(subnodebehind)) {
							 lastlinkindex=i;
							 break;
						 }
					 }
					 
					 //����������֮��ľ���
					 double lengthbetweentwonodes = 0.0;
					 for(int i =firstlinkindex;i<=lastlinkindex;i++) {
						 lengthbetweentwonodes=lengthbetweentwonodes+selectedpath.get(i).getLengthInKm();
					 }
					 
					 int numberofdcneeded=(int)Math.ceil(lengthbetweentwonodes/BPSKmaxlength)-1;
					 
					 List<Node> dcbetweentwonodes = new ArrayList<Node>();
					 
					 int numberofdcbetweentwonodes = 0;
					 
					 for(int i =firstlinkindex+1;i<=lastlinkindex;i++) {
						 if(subnodeonpath.get(i).getAttribute("DataCenter").equals("1")) {
							 dcbetweentwonodes.add(subnodeonpath.get(i));
							 numberofdcbetweentwonodes++;
						 }
					 }
					 
					//����֮��ľ���С��3000km
					 if(numberofdcneeded==0) {
						 //�ٿ�����֮����û���������ģ��еĻ����ڵ�һ����������
						 if(numberofdcbetweentwonodes>0) {
							 Node selecteddc = dcbetweentwonodes.get(0);
							 
							 if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 
							 vnfnodepair.put(undeployednode, selecteddc);
								
							 undeployednode.setAttribute("deployed", "1");
						     undeployednode.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
							 
						 }
						 
						 else{
							 //û�еĻ��ͷ��ھ���ǰһ�������������������
							 //��Ҫ�ж�ǰһ�����Ƿ������������ϣ��ڵĻ�ֱ�ӷ����������
							 //���ڵĻ�˵��ǰһ������Դ�ڵ㣬���ھ���Դ�ڵ�������������Ľڵ���
							 if(subnodebefore.getAttribute("DataCenter").equals("1")) {
								 Node selecteddc = subnodebefore;
								 if(subnodes.indexOf(selecteddc)<0) {
									 sign=false;
									 nodemappingreturn.setSign(sign);
									 return nodemappingreturn;
								 }
								 vnfnodepair.put(undeployednode, selecteddc);
									
								 undeployednode.setAttribute("deployed", "1");
							     undeployednode.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
									 
								 String a = selecteddc.getAttribute("VNF");
						    	 String b = undeployednode.getAttribute("VNF");
							     String c = a.concat(b);
						    	 selecteddc.setAttribute("VNF", c);
									 
								 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
										
								 reusability++;
										
								 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
							 }
							 
							 else {
								 //���ھ���Դ�ڵ����������������
								 for(int i = 0;i<subnodeonpath.size();i++) {
									 if(subnodeonpath.get(i).getAttribute("DataCenter").equals("1")) {
										 Node selecteddc = subnodeonpath.get(i);
										 if(subnodes.indexOf(selecteddc)<0) {
											 sign=false;
											 nodemappingreturn.setSign(sign);
											 return nodemappingreturn;
										 }
										 vnfnodepair.put(undeployednode, selecteddc);
											
										 undeployednode.setAttribute("deployed", "1");
									     undeployednode.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
											 
										 String a = selecteddc.getAttribute("VNF");
								    	 String b = undeployednode.getAttribute("VNF");
									     String c = a.concat(b);
								    	 selecteddc.setAttribute("VNF", c);
											 
										 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
												
										 reusability++;
												
										 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
										 
										 break;
									 }
								 }
							 }
							 
						 }
						 
					 }
					 
					 //ǰ��������֮��ľ������3000km�����������ֻ����3000-6000�����������ʵ��������ƣ�������֮��ľ��벻����ôԶ��
					 //����������֮�����ٻ�Ҫ��һ��DC����ȻBPSKҲ�����ˣ�����ֱ�Ӷ���
					 else {
						//������֮����û���������ģ��еĻ����ڵ�һ����������
						 if(numberofdcbetweentwonodes>0) {
							 Node selecteddc = dcbetweentwonodes.get(0);
							 if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 vnfnodepair.put(undeployednode, selecteddc);
								
							 undeployednode.setAttribute("deployed", "1");
						     undeployednode.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
							 
						 }
						 
					 }
					 
					 //�м�û���������ĵĻ��������κβ�����ͨ������nodepair��С�����ж��Ƿ�ӳ��ɹ�
					 
				 }
				 
				 
			 }
			 

			  
		 }
		 
		 
		 else { 
			 
			 List<Link> temppath = new ArrayList<Link>();
			 List<Node> nodeonpath = new ArrayList<Node>();
			 //����·�ϵ���������
			 List<Node> dcnodelist = new ArrayList<Node>();
			 //Դ��Ŀ�Ľڵ�֮�����������
			 List<Node> dcnodebetweensd=new ArrayList<Node>();
			 
			 for(int kth=0;kth<nodemappingknum;kth++) {
				 
				 temppath = kshortestpathlist.get(kth);
				
				 nodeonpath.clear();
				 dcnodelist.clear();
				 dcnodebetweensd.clear();
				 
				 nodeonpath.add(temppath.get(0).getOriginNode());
				 
				 for(Link link : temppath) {
					 nodeonpath.add(link.getDestinationNode());
				 }
				 
				 //����·�ϵ���������
				 for(Node node:nodeonpath) {
					 if(node.getAttribute("DataCenter").equals("1")) {
						 dcnodelist.add(node);
					 }
				 }
				 
				 //Դ��Ŀ�Ľڵ�֮�����������
				 for(int i=1;i<nodeonpath.size()-1;i++) {
					 if(nodeonpath.get(i).getAttribute("DataCenter").equals("1")) {
						 dcnodebetweensd.add(nodeonpath.get(i));
					 }
				 }
				 
				 if(!dcnodelist.isEmpty()) {
					 break;
				 }
				 
			 }
			 
			 if(dcnodelist.size()==0) {
				 sign = false;
				 nodemappingreturn.setSign(sign);
				 return nodemappingreturn;
			 }
			 
			 
			 double pathlength = 0.0;
			 for(Link link:temppath) {
				 pathlength=link.getLengthInKm()+pathlength;
			 }
			 
			 //Դ��Ŀ�Ľڵ�֮��������Ҫ���ٸ���������
			 int numberofdcneeded=(int)Math.ceil(pathlength/BPSKmaxlength)-1;
			 //Դ��Ŀ�Ľڵ�֮��ʵ���ж��ٸ���������
			 int numberoddcbetweensd=dcnodebetweensd.size();
			 //������Ҫ���ٸ�VNF
			 int numberofvnfneeded = vnfnodes.size();
			 
			 int middlenum=(int)Math.ceil((numberofvnfneeded*1.0)/2.0);
			 
			 //�ȿ���Դ��Ŀ�Ľڵ�֮�����С��3000km�����
			 if(numberofdcneeded==0) {
				 //�ٿ��м���û����������
				 if(numberoddcbetweensd==0) {
					 
					 //�м�û���������ĵĻ�ֻ�ܷ���Դ�ڵ��Ŀ�Ľڵ�����
					 Node selecteddc = dcnodelist.get(0);
					 for(int i=0;i<middlenum;i++) {
						 
						 Node undeployednode_before = vnfnodes.get(i);
						{
							if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							
							 vnfnodepair.put(undeployednode_before, selecteddc);
								
							 undeployednode_before.setAttribute("deployed", "1");
							 undeployednode_before.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode_before.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
						}
						
						 if(dcnodelist.size()>1) {
							 dcnodelist.remove(selecteddc);
							 selecteddc=dcnodelist.get(dcnodelist.size()-1);
						 }
						 
                         Node undeployednode_behind = vnfnodes.get(numberofvnfneeded-1-i);
						 
						{
							if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 vnfnodepair.put(undeployednode_behind, selecteddc);
								
							 undeployednode_behind.setAttribute("deployed", "1");
							 undeployednode_behind.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode_behind.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
						}
						
						if(dcnodelist.size()>1) {
							 dcnodelist.remove(selecteddc);
							 selecteddc=dcnodelist.get(0);
						 }
						
					 }
					 
				 }
				 
				 else {
					 //�м����������ĵĻ��Ͳ�����Դ�ڵ��Ŀ�Ľڵ���
					 
					 Node selecteddc = dcnodebetweensd.get(0);
					 for(int i=0;i<middlenum;i++) {
						 
						 Node undeployednode_before = vnfnodes.get(i);
						{
							
							if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 vnfnodepair.put(undeployednode_before, selecteddc);
								
							 undeployednode_before.setAttribute("deployed", "1");
							 undeployednode_before.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode_before.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
						}
						
						 if(dcnodebetweensd.size()>1) {
							 dcnodebetweensd.remove(selecteddc);
							 selecteddc=dcnodebetweensd.get(dcnodebetweensd.size()-1);
						 }
						 
                         Node undeployednode_behind = vnfnodes.get(numberofvnfneeded-1-i);
                         
	                     if(!undeployednode_behind.equals(undeployednode_before)){
	                    	 
	                    	 if(subnodes.indexOf(selecteddc)<0) {
	    						 sign=false;
	    						 nodemappingreturn.setSign(sign);
	    						 return nodemappingreturn;
	    					 }
								 vnfnodepair.put(undeployednode_behind, selecteddc);
									
								 undeployednode_behind.setAttribute("deployed", "1");
								 undeployednode_behind.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
									 
								 String a = selecteddc.getAttribute("VNF");
						    	 String b = undeployednode_behind.getAttribute("VNF");
							     String c = a.concat(b);
						    	 selecteddc.setAttribute("VNF", c);
									 
								 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
										
								 reusability++;
										
								 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
					    }
						
						if(dcnodebetweensd.size()>1) {
							dcnodebetweensd.remove(selecteddc);
							 selecteddc=dcnodebetweensd.get(0);
						 }
						
					 }
					 
				 
					 
				 }
				 
			 }
			 
			 //Դ��Ŀ�Ľڵ�֮��������3000km�����
			 //�м�����Ҫ��һ���������ģ���Ȼ����Ͷ���
			 else {
				 if(numberoddcbetweensd>0) {

					 Node selecteddc = dcnodebetweensd.get(0);
					 for(int i=0;i<middlenum;i++) {
						 
						 Node undeployednode_before = vnfnodes.get(i);
						{
							
							if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 vnfnodepair.put(undeployednode_before, selecteddc);
								
							 undeployednode_before.setAttribute("deployed", "1");
							 undeployednode_before.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode_before.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
						}
						
						 if(dcnodebetweensd.size()>1) {
							 dcnodebetweensd.remove(selecteddc);
							 selecteddc=dcnodebetweensd.get(dcnodebetweensd.size()-1);
						 }
						 
                         Node undeployednode_behind = vnfnodes.get(numberofvnfneeded-1-i);
						 
						{
							if(subnodes.indexOf(selecteddc)<0) {
								 sign=false;
								 nodemappingreturn.setSign(sign);
								 return nodemappingreturn;
							 }
							 vnfnodepair.put(undeployednode_behind, selecteddc);
								
							 undeployednode_behind.setAttribute("deployed", "1");
							 undeployednode_behind.setAttribute("MappedNode", String.valueOf(subnodes.indexOf(selecteddc)));
								 
							 String a = selecteddc.getAttribute("VNF");
					    	 String b = undeployednode_behind.getAttribute("VNF");
						     String c = a.concat(b);
					    	 selecteddc.setAttribute("VNF", c);
								 
							 int reusability = Integer.valueOf(selecteddc.getAttribute("Reusability")).intValue();
									
							 reusability++;
									
							 selecteddc.setAttribute("Reusability", String.valueOf(reusability));
						}
						
						if(dcnodebetweensd.size()>1) {
							dcnodebetweensd.remove(selecteddc);
							 selecteddc=dcnodebetweensd.get(0);
						 }
						
					 }
					 
				 }
			 }
			 
		 }
		 
		 nodepair.put(vnfsourcenode, SubNetPlan.getNode(sourcenodeindex));
		 
		 for(Node vnfnode:vnfnodes) {
			nodepair.put(vnfnode, vnfnodepair.get(vnfnode)); 
		 }
		 
		 nodepair.put(vnfdestinationnode, SubNetPlan.getNode(destinationnodeindex));
		 
		 if(nodepair.size()==numberofVNFnodes) {
			 //ȫ��ӳ��ɹ�
			 sign = true;
			 System.out.println("nodemapping success!");
//			 for(Node node:VNFnetplannodes) {
//				 System.out.println("the node"+"..."+node+"is mapped to Node"+subnodes.indexOf(nodepair.get(node)));
//				 System.out.println("confirm MappedNode "+node.getAttribute("MappedNode"));
//			 }
			 
		 }
		 else if(nodepair.size()!=numberofVNFnodes) {
				 System.out.println("nodempping failed!");
				 sign = false;
		 }
		 
		 for(Node node : vnfnodes) {
			 String s = node.getAttribute("MappedNode");
			 int subindex = Integer.valueOf(s).intValue();
			 if(subindex<0) {
				 sign = false;
				 break;
			 }
		 }
		 
		
		  if(sign) { 
			  for(Link link:vnflinklist) {
				  
				  int a = subnodes.indexOf(nodepair.get(link.getOriginNode()));
				  int b = subnodes.indexOf(nodepair.get(link.getDestinationNode()));
				  
				  if(a!=b) {
			
					  SubNetPlan.addDemand(nodepair.get(link.getOriginNode()),nodepair.get(link.getDestinationNode()), link.getCapacity(), null,SubNetPlan.getNetworkLayerDefault()); 
					  
				  }
				  
				  
			  } 
		  }
		 
		 
		 nodemappingreturn.setSign(sign);
		 
		 
		return nodemappingreturn;
		
	}
	

	
//	****************************************************************************************************************
/*
 * ͳ�������в����˶��ٸ�VNF
 */
	public static int numberofDeployedVNF(NetPlan SubNetPlan) {
		
		int numberofdeployedvnf=0;
		
		List<Node> subnodelist = SubNetPlan.getNodes();
		for(Node node:subnodelist) {
			if(node.getAttribute("DataCenter").equals("1")) {
				int num=node.getAttribute("VNF").length()-1;
				numberofdeployedvnf=numberofdeployedvnf+num;
			}
		}
		
		return numberofdeployedvnf;
		
	}

//	*************************************************************************************************************************************************
	/*
	 * ��·ӳ�����
	 * ����ÿ��VNFҵ�������󣬶�������һ��linkmapping����demand��
	 * ����ÿ��demand���Ȼ��demand��Դ��Ŀ�Ľڵ㣬ȡ��K�����·����·���ĳ��Ȳ��ܳ���3000km
	 * �Բ�����3000km��·�����б���������·���ĳ���ѡ����߽׵�����
	 * ������ȷ����֮�󣬸�����������ʣ�ȷ�������ز�slot����Ȼ��ѡ����ʵķ������ͽ�����
	 * ����ˣ�·�������ն�����Ƶ�׷�����������ƣ����ѡ������������СMFSI�ķ���
	 */
	
	public static LinkMappingReturn linkMapping(NetPlan VNFNetplan, NetPlan SubNetPlan) {
		
		LinkMappingReturn linkmappingreturn = new LinkMappingReturn();
		
		linkmappingsign = true;
		
		Tool_Util tool = new Tool_Util();
		
		
		//������������е����нڵ�
		List<Node> subnodes = SubNetPlan.getNodes();
		
		//������������е�ȫ��link
		List<Link> sublinks = SubNetPlan.getLinks(SubNetPlan.getNetworkLayerDefault());
		
		//��������е�demand
		List<Demand> demandlist = SubNetPlan.getDemands(SubNetPlan.getNetworkLayerDefault());
		
		System.out.println("the number of demands of this request is "+demandlist.size());
		
		
		for(Demand demand:demandlist) {
			
			//���������
			double capacity = demand.getOfferedTraffic();
			
			//�����ʼ��ķ������ز���Դ
			List<String> transmitterlist = new ArrayList<String>();
			
			//�����ֹ��Ľ������ز���Դ
			List<String> receiverlist = new ArrayList<String>();
			
			//�Ȼ��demand ����ʼ�ڵ�ͽ����ڵ㣬���������ڵ����K�����·��
			Node startnode = demand.getIngressNode();
			Node endnode = demand.getEgressNode();
			
			
			Map<Link,Double> linkCostMap = new HashMap<Link,Double>();
			for (Link link : sublinks){
					linkCostMap.put(link, link.getLengthInKm()); 
			}
			
			//�õ������ڵ�֮���K�����·��
			List<List<Link>> kshortestpathlist = GraphUtils.getKLooplessShortestPaths(subnodes, sublinks, startnode,endnode, linkCostMap, numberofkshortestpath, Double.MAX_VALUE, Integer.MAX_VALUE , Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
			
			//����������·�����ϣ�����С��3000km��
			List<List<Link>> candidatepathlist = new ArrayList<List<Link>>();
			
			//���ȴ���3000km��·����Ҫ
			for(int i=0;i<numberofkshortestpath;i++) {
				
				List<Link> temppath = kshortestpathlist.get(i);
				Double pathlength = 0.0;
				
				for(Link link:temppath) {
					pathlength=pathlength+link.getLengthInKm();
				}
				
				if(pathlength<=BPSKmaxlength) {
					candidatepathlist.add(temppath);
				}
				
			}
			
			if(candidatepathlist.size()==0) {
				//���û�п���·����ֱ�Ӷ���������ѭ��
				linkmappingsign=false;
				break;
			}
			
			else {
				
				transmitterlist.add(startnode.getAttribute("TransmitterOne"));
				transmitterlist.add(startnode.getAttribute("TransmitterTwo"));
				
				receiverlist.add(endnode.getAttribute("ReceiverOne"));
				receiverlist.add(endnode.getAttribute("ReceiverTwo"));
				
				//��¼ÿ�����·����Ԥ���������demand���MFSI
				List<Integer> mfsilist = new ArrayList<Integer>();
				//��¼�����ֵ�������
				List<String> indexcombinationlist = new ArrayList<String>();
				
				//��ʼ����
				for(int i =0;i<transmitterlist.size();i++) {
					for(int j=0;j<candidatepathlist.size();j++) {
						for(int k=0;k<receiverlist.size();k++) {
							
							
							
							//��i���������״̬
							String transmitter = transmitterlist.get(i);
							int[] transmitterstatus = tool.stringToIntArray(transmitter);
							
							//��k�����ջ���״̬
							String receiver = receiverlist.get(k);
							int[] receiverststus = tool.stringToIntArray(receiver);
							
							//��j����ѡ·��
							List<Link> temppath = candidatepathlist.get(j);
							
							//·���ĳ���
							Double pathlength = 0.0;
							for(Link link:temppath) {
								pathlength = pathlength+link.getLengthInKm();
							}
							
							double modlevel = 0.0;
							
							if(pathlength<=QAM_32maxlength) {
								modlevel=5.0;
							}
							else {
								
								if(pathlength<=QAM_16maxlength) {
									modlevel=4.0;
								}
								else {
									if(pathlength<=QAM_8maxlength) {
										modlevel=3.0;
									}
									else {
										if(pathlength<=QPSKmaxlength) {
											modlevel=2.0;
										}
										else {
											modlevel=1.0;
										}
									}
								} 
							}
							
						
						
							int numberofslotneeded = (int)Math.ceil(capacity/(12.5*modlevel));
//							System.out.println("speed�� "+capacity);
//							System.out.println("modlevel "+modlevel);
//							System.out.println("slotnum "+numberofslotneeded);
							
							int[] pathstatus = new int[numberofallslot];
							
							for(Link link:temppath) {
								
								String s = link.getAttribute("linkstatus");
								int[] s1 = tool.stringToIntArray(s);
								
								for(int m =0;m<numberofallslot;m++) {
									
									if(pathstatus[m]==0&&s1[m]==0) {
										pathstatus[m]=0;
									}
									else {
										pathstatus[m]=1;
									}	
								}
							}
							
							for(int m =0;m<numberofallslot;m++) {
								if(pathstatus[m]==0&&transmitterstatus[m]==0) {
									pathstatus[m]=0;
								}
								else {
									pathstatus[m]=1;
								}
							}
							
							for(int m =0;m<numberofallslot;m++) {
								if(pathstatus[m]==0&&receiverststus[m]==0) {
									pathstatus[m]=0;
								}
								else {
									pathstatus[m]=1;
								}
							}
							
							int startindex = 0;
							int endindex = 0;
							int flag=0;
							int count = 0;
							//�ҳ��������õ�slot���
							
							for(int m=0;m<numberofallslot;m++) {
								
								count++;
								
								if(pathstatus[m]==0) {
									flag++;
								}
								else {
									flag=0;
								}
								if(flag==numberofslotneeded) {
									endindex = m;
									startindex = endindex-numberofslotneeded+1;
									break;
								}
							}
							
							if(count==numberofallslot&&endindex==0) {
								break;
							}
							
							else {
								for(int m =startindex;m<=endindex;m++) {
									pathstatus[m]=1;
								}
							
								int mfsi=0;
								
								for(int m=0;m<numberofallslot;m++) {
									if(pathstatus[m]==1) {
										mfsi=m+1;
									}
								}
								
								mfsilist.add(mfsi);
								
								{
									String a = String.valueOf(i);
									String b = String.valueOf(j);
									String c = String.valueOf(k);
									String d = a.concat(b.concat(c));
									indexcombinationlist.add(d);
								}
								
							}
							
							
							
						}
					}
				}
				
				if(mfsilist.size()==0) {
					linkmappingsign=false;
					linkmappingreturn.setSign(linkmappingsign);
					
					return linkmappingreturn;
				}
				
				//�����������ҳ�����MFSI��С�ķ���
				int kmin = Collections.min(mfsilist);
				int kindex = mfsilist.indexOf(kmin);
				
				String scheme = indexcombinationlist.get(kindex);
				
				int[] choice = tool.stringToIntArray(scheme);
				
				String transimitter = transmitterlist.get(choice[0]);
				List<Link> selectedpath = candidatepathlist.get(choice[1]);
				String receiver = receiverlist.get(choice[2]);
				
				Double pathlength = 0.0;
				for(Link link: selectedpath) {
					pathlength=pathlength+link.getLengthInKm();
				}
				
				double modlevel = 0.0;
				
				if(pathlength<=QAM_32maxlength) {
					modlevel=5.0;
				}
				
				else {
					if(pathlength<=QAM_16maxlength) {
						modlevel=4.0;
					}
					else {
						if(pathlength<=QAM_8maxlength) {
							modlevel=3.0;
						}
						else {
							if(pathlength<=QPSKmaxlength) {
								modlevel=2.0;
							}
							else {
								modlevel=1.0;
							}
						}
					}
				}
				
				 
			
				
				String a = startnode.getAttribute("ActiveModulator");
				int mod = (int)modlevel;
				String b = String.valueOf(mod);
				String c = a.concat(b);
				startnode.setAttribute("ActiveModulator", c);
				
				int numberofslotneeded = (int)Math.ceil(capacity/(12.5*modlevel));
				
//				for(Link link:selectedpath) {
//					System.out.print(subnodes.indexOf(link.getOriginNode()));
//					System.out.print("..");
//					System.out.print(subnodes.indexOf(link.getDestinationNode()));
//					System.out.print("   ");
//				}
//				
//				System.out.println();
//				
//				System.out.println("length of this path is : "+pathlength);
//				System.out.println("selected mod level is : "+mod);
//				System.out.println("number of needed slot is : "+numberofslotneeded);
//				System.out.println("Modulator ststus before mapping : "+a);
//				System.out.println("Modulator ststus after mapping : "+c);
				
				int[] transimitterstatus = tool.stringToIntArray(transimitter);
				int[] receiverstatus = tool.stringToIntArray(receiver);
				
//				System.out.println("Transmitter " +choice[0]+" status before mapping: ");
//			    for(int m=0;m<numberofallslot;m++) {
//					System.out.print(transimitterstatus[m]);
//				}
//			    System.out.println();
//			    
//			    System.out.println("Receiver "+choice[2]+" status before mapping: ");
//			    for(int m=0;m<numberofallslot;m++) {
//					System.out.print(receiverstatus[m]);
//				}
//			    System.out.println();
				
				int pathstatus[] = new int[numberofallslot];
				
				for(Link link:selectedpath) {
					
					String s = link.getAttribute("linkstatus");
					int[] s1 = tool.stringToIntArray(s);
					
					for(int m =0;m<numberofallslot;m++) {
						
						if(pathstatus[m]==0&&s1[m]==0) {
							pathstatus[m]=0;
						}
						else {
							pathstatus[m]=1;
						}	
					}
				}
				
				for(int m = 0;m<numberofallslot;m++) {
					if(pathstatus[m]==0&&transimitterstatus[m]==0) {
						pathstatus[m]=0;
					}
					else {
						pathstatus[m]=1;
					}	
				}
				
				for(int m = 0;m<numberofallslot;m++) {
					if(pathstatus[m]==0&&receiverstatus[m]==0) {
						pathstatus[m]=0;
					}
					else {
						pathstatus[m]=1;
					}	
				}
				
//				for(Link link:selectedpath) {
//					System.out.print(subnodes.indexOf(link.getOriginNode()));
//					System.out.print("..");
//					System.out.print(subnodes.indexOf(link.getDestinationNode()));
//					System.out.println();
//				}
//				
//				System.out.println("slot status of subpath before mapping: ");
//				for(int i=0;i<numberofallslot;i++) {
//					System.out.print(pathstatus[i]);
//				}
//				System.out.println();
				
				int startindex = 0;
				int endindex = 0;
				int flag=0;
				//�ҳ��������õ�slot���
				
				for(int m=0;m<numberofallslot;m++) {
					if(pathstatus[m]==0) {
						flag++;
					}
					else {
						flag=0;
					}
					if(flag==numberofslotneeded) {
						endindex = m;
						startindex = endindex-numberofslotneeded+1;
						break;
					}
				}
				
				for(int m=startindex;m<=endindex;m++) {
					transimitterstatus[m]=1;
				}
				
				String transimitterstatus_1 = tool.intArrayToString(transimitterstatus);
				if(choice[0]==0) {
					startnode.setAttribute("TransmitterOne", transimitterstatus_1);
				}
				else {
					startnode.setAttribute("TransmitterTwo", transimitterstatus_1);
				}
				
//				System.out.println("Transmitter " +choice[0]+" status after mapping: ");
//			    for(int m=0;m<numberofallslot;m++) {
//					System.out.print(transimitterstatus[m]);
//				}
//			    System.out.println();
				
				for(int m=startindex;m<=endindex;m++) {
					receiverstatus[m]=1;
				}
				String receiverstatus_1 = tool.intArrayToString(receiverstatus);
				if(choice[2]==0) {
					endnode.setAttribute("ReceiverOne", receiverstatus_1);
				}
				else {
					endnode.setAttribute("ReceiverTwo", receiverstatus_1);
				}
				
//				System.out.println("Receiver "+choice[2]+" status after mapping: ");
//			    for(int m=0;m<numberofallslot;m++) {
//					System.out.print(receiverstatus[m]);
//				}
//			    System.out.println();
			    
                for(Link link:selectedpath) {
					
					String s = link.getAttribute("linkstatus");
					int[] s1 = tool.stringToIntArray(s);
					
					for(int i =startindex;i<=endindex;i++) {
						s1[i]=1;
					}
					
					s = tool.intArrayToString(s1);
					
					link.setAttribute("linkstatus", s);
					
//					System.out.println("link "+subnodes.indexOf(link.getOriginNode())+"..."+subnodes.indexOf(link.getDestinationNode())+"slot status after linkmapping ");
//					System.out.println(s);
					
					linkmappingsign=true;
					
				}
				
			}
			
		}
		
		linkmappingreturn.setSign(linkmappingsign);
		
		return linkmappingreturn;
		
		
	}
	
//	*************************************************************************************************************************************************
	/*
	 * ͳ�������е�MFSI
	 */
	
	public static int MFSI(NetPlan SubNetPlan) {
		
		int mfsiindex=0;
		
		Tool_Util tool = new Tool_Util();
		
		//������������е�����link
		List<Link> subnetplanlinklist = SubNetPlan.getLinks(SubNetPlan.getNetworkLayerDefault());
		
		//���ÿ��link���������slot�����
		List<Integer> maxindexlist = new ArrayList<Integer>();
		
		for(Link link:subnetplanlinklist) {
			
			String s = link.getAttribute("linkstatus");
			int[] s1 = tool.stringToIntArray(s);
			
			int max = 0;
			
			for(int i =0;i<numberofallslot;i++) {
				if(s1[i]==1) {
					max=i;
				}
			}
			maxindexlist.add(max);
		}
		
		mfsiindex = Collections.max(maxindexlist);
		
		
		return mfsiindex+1;
		
	}
	
//	*************************************************************************************************************************************************
	/*
	 * ͳ�������е�����������
	 */
	public static int AllActiveModulator(NetPlan SubNetplan) {
		int numberofallactivemodulator=0;
		
		List<Node> subnodes = new ArrayList<Node>();
		subnodes=SubNetplan.getNodes();
		
		for(Node node:subnodes) {
			String s = node.getAttribute("ActiveModulator");
			int num = s.length()-1;
			numberofallactivemodulator=numberofallactivemodulator+num;
		}
		
		
		return numberofallactivemodulator;
	}
	
//*******************************************************************************************************************************************************
	/*
	 * ͳ��������BPSK������
	 */
	public static int ActiveBPSK(NetPlan SubNetplan) {
		int numberofactiveBPSK=0;
		
		Tool_Util tool = new Tool_Util();
		
		List<Node> subnodes = new ArrayList<Node>();
		subnodes=SubNetplan.getNodes();
		
		for(Node node : subnodes) {
			String s = node.getAttribute("ActiveModulator");
			int[] s1 = tool.stringToIntArray(s);
			
			for(int i:s1) {
				if(i==1) {
					numberofactiveBPSK++;
				}
			}
		}
		
		return numberofactiveBPSK;
	}
	
	
	//*******************************************************************************************************************************************************
		/*
		 * ͳ��������QPSK������
		 */
		public static int ActiveQPSK(NetPlan SubNetplan) {
			int numberofactiveQPSK=0;
			
			Tool_Util tool = new Tool_Util();
			
			List<Node> subnodes = new ArrayList<Node>();
			subnodes=SubNetplan.getNodes();
			
			for(Node node : subnodes) {
				String s = node.getAttribute("ActiveModulator");
				int[] s1 = tool.stringToIntArray(s);
				
				for(int i:s1) {
					if(i==2) {
						numberofactiveQPSK++;
					}
				}
			}
			
			return numberofactiveQPSK;
		}
	
	
	
	//*******************************************************************************************************************************************************
				/*
				 * ͳ��������8QAM������
				 */
				public static int Active8QAM(NetPlan SubNetplan) {
					int numberofactive8QAM=0;
					
					Tool_Util tool = new Tool_Util();
					
					List<Node> subnodes = new ArrayList<Node>();
					subnodes=SubNetplan.getNodes();
					
					for(Node node : subnodes) {
						String s = node.getAttribute("ActiveModulator");
						int[] s1 = tool.stringToIntArray(s);
						
						for(int i:s1) {
							if(i==3) {
								numberofactive8QAM++;
							}
						}
					}
					
					return numberofactive8QAM;
				}
			
	
			//*******************************************************************************************************************************************************
				/*
				 * ͳ��������16QAM������
				 */
				public static int Active16QAM(NetPlan SubNetplan) {
					int numberofactive16QAM=0;
					
					Tool_Util tool = new Tool_Util();
					
					List<Node> subnodes = new ArrayList<Node>();
					subnodes=SubNetplan.getNodes();
					
					for(Node node : subnodes) {
						String s = node.getAttribute("ActiveModulator");
						int[] s1 = tool.stringToIntArray(s);
						
						for(int i:s1) {
							if(i==4) {
								numberofactive16QAM++;
							}
						}
					}
					
					return numberofactive16QAM;
				}
				
			/* *********************************************************** */
				/*
				 * ͳ��������32QAM������
				 */
				public static int Active32QAM(NetPlan SubNetplan) {
					int numberofactive32QAM=0;
					
					Tool_Util tool = new Tool_Util();
					
					List<Node> subnodes = new ArrayList<Node>();
					subnodes=SubNetplan.getNodes();
					
					for(Node node : subnodes) {
						String s = node.getAttribute("ActiveModulator");
						int[] s1 = tool.stringToIntArray(s);
						
						for(int i:s1) {
							if(i==5) {
								numberofactive32QAM++;
							}
						}
					}
					
					return numberofactive32QAM;
				}	
				
				
			//�󼯺ϵ�ƽ��ֵ
				
			public static double getAvgvalue(List<Integer> list) {
				
				double avgvalue = 0.0;
				double sum = 0.0;
				int num = list.size();
				
				for(int i : list) {
					
					sum = (double)i+sum;
					
				}
				
				avgvalue = sum/(num*1.0);
				
				
				
				return avgvalue;
				
			}
			
			public static double getDoubleAvgvalue(List<Double> list) {
				
				double avgvalue = 0.0;
				double sum = 0.0;
				int num = list.size();
				
				for(double i : list) {
					
					sum = (double)i+sum;
					
				}
				
				avgvalue = sum/(num*1.0);
				
				
				
				return avgvalue;
			}

			
			
			
/* *********************************************** */
//ͳ��������һ���ж��ٸ�slot��ռ��
			
			public static int busySlot(NetPlan SubNetplan) {
				
				Tool_Util tool = new Tool_Util();
				
				int num=0;
				
				List<Link> sublinklist = SubNetplan.getLinks(SubNetplan.getNetworkLayerDefault());
				
				for(Link link:sublinklist) {
					
					String s = link.getAttribute("linkstatus");
					int[] s1 = tool.stringToIntArray(s);
					
					for(int i =0;i<numberofallslot;i++) {
						if(s1[i]==1) {
							num++;
						}
					}
					
				}
				
				return num;
				
			}
			
	//ͳ��ƽ��MFSI
			public static double AvgMFSI(NetPlan SubNetPlan) {
				
				double avgmfsi=0.0;
				
				Tool_Util tool = new Tool_Util();
				
				//������������е�����link
				List<Link> subnetplanlinklist = SubNetPlan.getLinks(SubNetPlan.getNetworkLayerDefault());
				
				
				//���ÿ��link���������slot�����
				List<Integer> maxindexlist = new ArrayList<Integer>();
				
				for(Link link:subnetplanlinklist) {
					
					String s = link.getAttribute("linkstatus");
					int[] s1 = tool.stringToIntArray(s);
					
					int max = 0;
					
					for(int i =0;i<numberofallslot;i++) {
						if(s1[i]==1) {
							max=i;
						}
					}
					maxindexlist.add(max+1);
				}
				
				avgmfsi = getAvgvalue(maxindexlist);
				
				return avgmfsi;
				
			}
	
}